package com.joelapenna.foursquare.util;

import java.util.ArrayList;

import com.joelapenna.foursquare.types.Category;
import com.joelapenna.foursquare.types.Group;

public class CategoryUtils {

	private static final String SEPARATOR = ",";
	private static final String CHILD_SEPARATOR = ";"; // HACK Use different separator for child lists, this way simple .split() works for top level list
	
	/**
	 *  Generates one string out of given category hieararchies.
	 *  
	 *  String serves two purposes: When changing settings, we need categories at the level
	 *  user has chosen to save them. However, when using the list against a list of venues,
	 *  we need lower level ids as well. We cannot be sure that the hierarchy is at hand in client,
	 *  and we don't want to make extra server calls.
	 * 
	 *  Returns a comma-separated list. Each element is either a leaf member id, or an 
	 *  id of higher level followed by a comprehensive list of lower level ids in brackets.
	 *  
	 *  Eg.
	 *  
	 *  1[56;57;69;89],102,104,20[99;100]
	 *
	 *  Here, user has chosen to save categories 1, 102, 104 and 20. 
	 *  Categories with id 1 and 20 are not leaves, 
	 *  and a list of lower level children is given in brackets.
	 *  Categories 102, 104 are leaves.
	 *  
	 *  
	 * @param categories
	 * @return
	 */
	public static String generatePreferencesString(Group<Category> categories) {
		if (categories == null || categories.size() == 0)
			return null;
		
		String prefStr = "";
		
		for (Category category : categories) {
			if (prefStr.length()>0)
				prefStr += SEPARATOR;
			
			prefStr += category.getId();
			
			String childStr = getCategoryIdLineage(category.getChildCategories());
			
			if (childStr != null && childStr.length() > 0)
				prefStr += "[" + childStr + "]";
		}
		
		return prefStr;
	}
	
	public static ArrayList<String> getCategoryIdLineageFromPreferencesString(String preferencesString) {
    	
		if (preferencesString == null || preferencesString.length() == 0) 
			return null;

		ArrayList<String> categoryIds = new ArrayList<String>(); // final list

		String[] categories = preferencesString.split(SEPARATOR); // raw list
		
		for (String category : categories) {
			if (category.charAt(category.length()-1) == ']') {
				String childStr = category.substring(category.indexOf('[')+1, category.length()-1);
				String parentStr = category.substring(0, category.indexOf('['));
				
				categoryIds.add(parentStr);
				
				String[] children = childStr.split(CHILD_SEPARATOR);
				
				for (String child : children) {
					categoryIds.add(child);
				}
			}
			else {
				categoryIds.add(category);
			}
		}
		
		return categoryIds;

	}
	
	public static ArrayList<String> getSelectionLevelCategoryIdsFromPreferencesString(String preferencesString) {
		if (preferencesString == null || preferencesString.length() == 0) 
			return null;
		
		ArrayList<String> categoryIds = new ArrayList<String>(); // final list

		String[] categories = preferencesString.split(SEPARATOR); // raw list
		
		for (String category : categories) {
			if (category.indexOf('[')>=0) {
				String parentStr = category.substring(0, category.indexOf('['));
				categoryIds.add(parentStr);
			}
			else {
				categoryIds.add(category); // leaf level selection
			}
		}
		
		return categoryIds;
		
	}
	
	private static String getCategoryIdLineage(Group<Category> categories) {
		if (categories == null || categories.size() == 0)
			return null;
		
		String categoryIds = "";
		
		for (Category category : categories) {
			if (categoryIds.length()>0)
				categoryIds += CHILD_SEPARATOR;

			categoryIds += getCategoryIdLineage(category); 
		}
		
		return categoryIds;
		
	}
	
	private static String getCategoryIdLineage(Category category) {
		
		String categoryIds = category.getId();

		if (category.getChildCategories() == null || category.getChildCategories().size() == 0)
			return categoryIds;
		
		for (Category child : category.getChildCategories()) {
			if (categoryIds.length()>0)
				categoryIds += CHILD_SEPARATOR;
			
			categoryIds += getCategoryIdLineage(child);
		}
		
		return categoryIds;
	}
	
}
